package utils

import (
	"fmt"
	"nodemessage.com/ruov-cli/config"
	"os"
	"time"

	"github.com/fatih/color"
	"gopkg.in/ini.v1"
	"nodemessage.com/ruov-cli/consts"
	"nodemessage.com/ruov-cli/rlog"
)

// 配置文件相关操作

// LoadSetting 从配置文件加载全局配置到结构体
func LoadSetting() (*config.Setting, error) {
	if _, err := os.Stat(consts.SettingFile); os.IsNotExist(err) {
		return nil, fmt.Errorf("配置文件不存在: %v", err)
	}

	cfg, err := ini.Load(consts.SettingFile)
	if err != nil {
		return nil, fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 映射到结构体
	var config config.Setting
	err = cfg.MapTo(&config)
	if err != nil {
		return nil, fmt.Errorf("映射配置到结构体失败: %v", err)
	}

	return &config, nil
}

// SaveSetting 保存全局配置到配置文件
func SaveSetting(config *config.Setting) error {
	cfg := ini.Empty()
	err := ini.ReflectFrom(cfg, config)
	if err != nil {
		return fmt.Errorf("从结构体反射到配置失败: %v", err)
	}

	// 确保目录存在
	dir := consts.ConfPath
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err = os.MkdirAll(dir, os.ModePerm)
		if err != nil {
			return fmt.Errorf("创建配置目录失败: %v", err)
		}
	}

	// 保存到文件
	if err := cfg.SaveTo(consts.SettingFile); err != nil {
		return fmt.Errorf("保存配置文件失败: %v", err)
	}

	return nil
}

// GetConfigValue 获取特定节和键的值
func GetConfigValue(section, key string) (string, error) {
	// 检查section是否允许
	if !config.IsAllowedSection(section) {
		return "", fmt.Errorf("配置节 [%s] 不允许读取", section)
	}

	// 加载配置
	cfg, err := ini.Load(consts.SettingFile)
	if err != nil {
		return "", fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 检查节是否存在
	sec, err := cfg.GetSection(section)
	if err != nil {
		return "", fmt.Errorf("节 [%s] 不存在", section)
	}

	// 检查键是否存在
	k, err := sec.GetKey(key)
	if err != nil {
		return "", fmt.Errorf("键 %s 在节 [%s] 中不存在", key, section)
	}

	return k.Value(), nil
}

// SetConfigValue 设置特定节和键的值，并限制部分键的写入
func SetConfigValue(section, key, value string) error {
	// 检查section是否允许
	if !config.IsAllowedSection(section) {
		rlog.Logger.Error("修改受限配置节: %s", section)
		color.Red("配置节 [%s] 不允许修改", section)
		return fmt.Errorf("配置节 [%s] 不允许修改", section)
	}

	// 检查key是否受限
	if config.IsKeyRestricted(section, key) {
		rlog.Logger.Error("修改受限配置键: %s.%s", section, key)
		color.Red("配置键 [%s] %s 不允许直接修改", section, key)
		return fmt.Errorf("配置键 [%s] %s 不允许直接修改", section, key)
	}

	// 加载配置
	cfg, err := ini.Load(consts.SettingFile)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 获取或创建节
	sec, err := cfg.GetSection(section)
	if err != nil {
		// 创建节
		sec, err = cfg.NewSection(section)
		if err != nil {
			return fmt.Errorf("创建配置节失败: %v", err)
		}
	}

	// 设置值
	_, err = sec.NewKey(key, value)
	if err != nil {
		return fmt.Errorf("设置配置值失败: %v", err)
	}

	// 保存
	if err := cfg.SaveTo(consts.SettingFile); err != nil {
		return fmt.Errorf("保存配置文件失败: %v", err)
	}

	return nil
}

// InitDefaultConfig 初始化默认配置（如果不存在）
func InitDefaultConfig() error {
	// 检查配置文件是否存在
	if _, err := os.Stat(consts.SettingFile); err == nil {
		// 文件已存在，不需要初始化
		return nil
	}

	// 创建默认配置
	config := &config.Setting{}

	// 设置默认值
	config.App.Name = "ruov-cli"
	config.App.Version = "1.0.0"
	config.App.Author = "wjsmc"

	// 设置内部配置
	config.Internal.InstallTime = time.Now().Format("2006-01-02 15:04:05")
	config.Internal.RunCount = 0

	// 保存配置
	return SaveSetting(config)
}

// UpdateInternalStats 更新内部统计信息
func UpdateInternalStats() error {
	// 加载配置
	cfg, err := ini.Load(consts.SettingFile)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 获取内部节，如果不存在则创建
	sec, err := cfg.GetSection("internal")
	if err != nil {
		sec, err = cfg.NewSection("internal")
		if err != nil {
			return fmt.Errorf("创建内部配置节失败: %v", err)
		}
	}

	// 更新上次使用时间
	_, err = sec.NewKey("last_used", time.Now().Format("2006-01-02 15:04:05"))
	if err != nil {
		return fmt.Errorf("更新上次使用时间失败: %v", err)
	}

	// 获取并增加运行次数
	runCountKey, err := sec.GetKey("run_count")
	if err != nil {
		// 键不存在，创建并设置为1
		_, err = sec.NewKey("run_count", "1")
		if err != nil {
			return fmt.Errorf("设置运行次数失败: %v", err)
		}
	} else {
		// 键存在，增加计数
		runCount := runCountKey.MustInt(0) + 1
		runCountKey.SetValue(fmt.Sprintf("%d", runCount))
	}

	// 保存配置
	if err := cfg.SaveTo(consts.SettingFile); err != nil {
		return fmt.Errorf("保存配置文件失败: %v", err)
	}

	return nil
}

// IsAllowedSection 检查节是否允许读写
func IsAllowedSection(section string) bool {
	return config.IsAllowedSection(section)
}
